package lg.minecraft.plugin.library.command;

import lg.minecraft.plugin.library.command.arg.ArgType;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author langle__
 * @version 1.0
 */
@Getter
public abstract class BaseCommand implements LGCommandExecutor {

    protected final String name;
    protected final String[] aliases;

    public BaseCommand(String name){
        this.name = name;
        this.aliases = new String[]{};
    }

    public BaseCommand(String name, String... aliases) {
        this.name = name.toLowerCase();
        this.aliases = Arrays.stream(aliases)
                .map(String::toLowerCase)
                .toArray(String[]::new);
    }

    /**
     * 获取当前命令的权限点
     *
     * @return String 返回权限点
     */
    public String getPermission() {
        return null;
    }

    /**
     * 获取命令类型，默认为 CommandType.ALL
     *
     * @return CommandType 命令类型的枚举值
     */
    public CommandType getCommandType() {
        return CommandType.ALL;
    }

    @Nullable
    public ArgType[] getArgList() {
        return null;
    }

    /**
     * 检查发送命令的用户是否有权限执行此命令
     *
     * @param sender 命令的发送者，可以是玩家、控制台
     * @return 如果发送者有权限或发送者是控制台，则返回true；否则返回false
     */
    public boolean isPermission(CommandSender sender) {
        // 如果发送者是控制台，则始终有权限
        if (sender instanceof ConsoleCommandSender) {
            return true;
        }
        // 获取执行此命令所需的权限节点
        String permission = this.getPermission();
        // 如果此命令不需要特定权限，则发送者始终有权限
        if (permission == null || permission.isEmpty()) {
            return true;
        }
        // 检查发送者是否具有所需的权限
        return sender.hasPermission(permission);
    }

    @Override
    public List<String> onTabComplete(CommandContext context) {
        return null;
    }

    /**
     * 判断给定的命令名称是否匹配此命令的主名或别名
     *
     * @param commandName 要检查的命令名称
     * @return 如果匹配则返回 true
     */
    public boolean isCommandName(String commandName) {
        if (commandName.equalsIgnoreCase(name)) {
            return true;
        }
        return Arrays.stream(aliases).anyMatch(commandName::equalsIgnoreCase);
    }

    /**
     * 根据给定的参数arg，从列表list中筛选出匹配的字符串
     * 如果arg为空，则直接返回原始列表；否则，返回所有以arg开头的字符串，不区分大小写
     *
     * @param arg 用于筛选的字符串
     * @param list 被筛选的字符串列表
     * @return 匹配的字符串列表
     */
    protected List<String> tabValue(String arg, List<String> list) {
        // 当给定的参数arg为空时，直接返回原始列表，无需筛选
        if (arg.isEmpty()) {
            return list;
        } else {
            // 创建一个新的列表，用于存储匹配的字符串
            List<String> values = new ArrayList<>();
            // 遍历列表中的每个字符串
            for (String str : list) {
                // 使用正则表达式进行匹配，(?i)表示不区分大小写，^arg表示以arg开头，.*$表示后续任意字符
                if (str.matches("(?i)^" + arg + ".*$")) {
                    // 如果字符串匹配，将其添加到匹配列表中
                    values.add(str);
                }
            }
            // 返回匹配的字符串列表
            return values;
        }
    }

    /**
     * 根据玩家名称获取在线玩家的名称列表
     * 该方法用于生成在线玩家名称的列表，以便在输入玩家名称时提供自动补全功能
     *
     * @param playerName 玩家名称的前缀，用于过滤和匹配在线玩家名称
     * @return 返回一个字符串列表，包含与玩家名称前缀匹配的在线玩家名称
     */
    protected List<String> tabValuePlayerName(String playerName) {
        // 初始化一个空的玩家名称列表，用于存储在线玩家的名称
        List<String> playerNameList = new ArrayList<>();

        // 遍历所有在线玩家，并将他们的名称添加到列表中
        for (Player player : Bukkit.getOnlinePlayers()) {
            playerNameList.add(player.getName());
        }

        // 调用tabValue方法，使用玩家名称前缀过滤列表，并返回结果
        return tabValue(playerName, playerNameList);
    }

}
